﻿using System;
using System.Collections.Generic;
using System.Text;
using Stauffware.Common.Xml.Xerialization;

namespace Zoo_1
{
	/*
	 *	Class inheritance summary
	 *	
	 *		Enclosure
	 *			Cage
	 *			Compound
	 *		Animal
	 *			Mammal
	 *				Ferret
	 *			Bird
	 *				Parrot
	 * 
	 *	Object containment summary
	 * 
	 *		Zoo
	 *			Exhibits[]
	 *				Enclosure
	 *					Barrier
	 *				Animal[]
	 */

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Zoo
	{
		public List<Exhibit> Exhibits;

		[XerialMember(Encoding=MemberValueEncoding.ImplicitValueType)]
		public string Remarks;

		[XerialMember(Encoding=MemberValueEncoding.ImplicitValueType)]
		public List<string> Journal;

		public Zoo ()
		{
			this.Exhibits = new List<Exhibit>();
		}

		public static Zoo CreateSample1 ()
		{
			Zoo zoo = new Zoo();
			zoo.Remarks = "Hello, zoo!";

			zoo.Exhibits.Add(new Exhibit(new Cage(17), 
							new Parrot("Polly", 99, 1.23M, false)));
			zoo.Exhibits.Add(new Exhibit(new Compound(23, Barrier.Moat),
							 new Ferret("Fred", 2), new Ferret("George", 3)));

			zoo.Journal = new List<string>();
			zoo.Journal.Add("foo");
			zoo.Journal.Add("Twas brillig, and the slithy toves...");

			return zoo;
		}

		public static readonly Type[] XerialTypes =
		{
			typeof(Zoo), typeof(Exhibit), typeof(Animal), typeof(Ferret), typeof(Parrot),
			typeof(Bird), typeof(Mammal), typeof(Cage), typeof(Compound)
		};
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Exhibit
	{
		public Enclosure Enclosure;
		public List<Animal> Inmates;

		public Exhibit ( ) { }

		public Exhibit (Enclosure enc, params Animal[] inmates)
		{
			this.Enclosure = enc;
			this.Inmates = new List<Animal>(inmates);
		}
	}

	//=================================================================================
	/// <summary>
	/// This enum serves as test data for Xerialization unit tests.
	/// </summary>

	public enum Barrier
	{
		None = 0, Bars, Fence, Moat
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>
	
	[XerialType]
	public abstract class Enclosure
	{
		public abstract Barrier Barrier { get; }
		public int Area;

		public Enclosure ( ) { }

		protected Enclosure (int area)
		{
			this.Area = area;
		}
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>
	
	[XerialType]
	public class Cage : Enclosure
	{
		public override Barrier Barrier
		{
			get { return Barrier.Bars; }
		}

		public Cage ( ) { }

		public Cage (int area)
			: base(area)
		{
		}
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Compound : Enclosure
	{
		public override Barrier Barrier
		{
			get { return this._barrier; }
		}
		private Barrier _barrier;

		public Compound ( ) { }

		public Compound (int area, Barrier barrier)
			: base(area)
		{
			this._barrier = barrier;
		}
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public abstract class Animal
	{
		public float Age;
		public string Name;

		public Animal ( ) { }

		protected Animal (string name, float age)
		{
			this.Age = age;
			this.Name = name;
		}
	}

	//---------------------------------------------------------------------------------
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Mammal : Animal	// logically abstract, but left concrete as an additional testcase
	{
		public bool HasTail;

		public Mammal ( ) { }

		protected Mammal (string name, float age, bool hasTail)
			: base(name, age)
		{
			this.HasTail = hasTail;
		}
	}

	//---------------------------------------------------------------------------------
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Ferret : Mammal
	{
		public Ferret ( ) { }

		public Ferret (string name, float age)
			: base(name, age, true)
		{
		}
	}

	//---------------------------------------------------------------------------------
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public abstract class Bird : Animal
	{
		public decimal Wingspan;

		public Bird ( ) { }

		protected Bird (string name, float age, decimal wingspan)
			: base(name, age)
		{
			this.Wingspan = wingspan;
		}
	}

	//=================================================================================
	/// <summary>
	/// This class serves as test data for Xerialization unit tests.
	/// </summary>

	[XerialType]
	public class Parrot : Bird
	{
		public bool PiningForTheFjords;

		public Parrot ( ) { }

		public Parrot (string name, float age, decimal wingspan, bool pining)
			: base(name, age, wingspan)
		{
			this.PiningForTheFjords = pining;
		}
	}

	//=================================================================================
}
